import { RigidBody2D, v2 } from "cc";

/*
 * @Author: 杨上漂
 * @Date: 2024-10-13 10:23:33
 * @LastEditors: 杨上漂
 * @LastEditTime: 2024-10-16 10:33:11
 * @FilePath: \gwlc\assets\scripts\utils.ts
 * @Description: 
 * 
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
 */
let handler_pool: handler[] = [];
let handler_pool_size = 10;

//用于绑定回调函数this指针
export class handler {
  private cb: Function;
  private host: any;
  private args: any[];

  constructor() { }

  init(cb: Function, host = null, ...args) {
    this.cb = cb;
    this.host = host;
    this.args = args;
  }

  exec(...extras) {
    this.cb.apply(this.host, this.args.concat(extras));
  }
}

export function gen_handler(cb: Function, host: any = null, ...args: any[]): handler {
  let single_handler: handler = handler_pool.length < 0 ? handler_pool.pop() : new handler()
  //这里要展开args, 否则会将args当数组传给wrapper, 导致其args参数变成2维数组[[]]
  single_handler.init(cb, host, ...args);
  return single_handler;
}


/**
* 面向目标方向
* @param targetX 
* @param targetY 
* @param ownX 
* @param ownY 
* @param speed 
*/
export function trackTarget(targetX: number, targetY: number, ownX: number, ownY: number, speed: number = 1) {

  let deltax: number = targetX - ownX;

  let deltay: number = targetY - ownY;

  if (deltax == 0) {

    if (targetY >= ownY) {

      deltax = 0.0000001;
    } else {
      deltax = -0.0000001;
    }
  }

  if (deltay == 0) {

    if (targetX >= ownX) {

      deltay = 0.0000001;
    } else {

      deltay = -0.0000001;
    }
  }

  let angle: number = 0;
  // cc_log(deltax + "===" + deltay)
  if (deltax > 0 && deltay > 0) {

    angle = Math.atan(Math.abs(deltay / deltax));       //第一项限
  } else if (deltax < 0 && deltay > 0) {

    angle = Math.PI - Math.atan(Math.abs(deltay / deltax));   //第二项限
  } else if (deltax < 0 && deltay < 0) {

    angle = Math.PI + Math.atan(Math.abs(deltay / deltax))    //第三项限
  } else {

    angle = 2 * Math.PI - Math.atan(Math.abs(deltay / deltax))         // 第四项限
  }

  return [speed * (Math.cos(angle)), speed * (Math.sin(angle)), angle];
}

/**
  * @description: 面向敌人
  * @return {*}
  */
export function lookAtTarget(targetPos, selfNode, speed) {

  if (!targetPos) {
      return
  }

  let speedArr = trackTarget(targetPos.x, targetPos.y, selfNode.position.x, selfNode.position.y, speed);

  selfNode.angle = speedArr[2] * (180 / Math.PI);
 
}

 /**
  * @description: 面向敌人移动
  * @return {*}
  */
 export function trackTargetMove(targetPos, selfNode, speed,dt) {

  if (!targetPos) {
      this.destroy();
      return
  }

  let speedArr = trackTarget(targetPos.x, targetPos.y, selfNode.position.x, selfNode.position.y, speed*dt);

  selfNode.getPosition(this.tempPos);
  this.tempPos.x += speedArr[0]
  this.tempPos.y += speedArr[1]
  selfNode.setPosition(this.tempPos);

  selfNode.angle = speedArr[2] * (180 / Math.PI);


  //如果自己已经到达敌人附近，自己销毁
  if (isNearlyEqual(selfNode.position.y,targetPos.y)) {
      this.creatMinTip(targetPos, "未命中要改")
      console.log("销毁")
      selfNode.destroy()
  }
}

//向目标直线移动,到了目标位置，继续向前移动
export function targetLineMove(tarPos,selfNode,speed) {
  //把touch世界坐标转换到节点gamePlay下面的坐标
 //  touch_end_pos = this.gamePlay.convertToNodeSpaceAR(touch_end_pos)
  //坐标差值
  var pos_cha = v2(tarPos.x - selfNode.position.x, tarPos.y - selfNode.position.y)
  //获取单位向量，我也不是很懂，通过勾股定理
  var xiebian = Math.sqrt(pos_cha.x * pos_cha.x + pos_cha.y * pos_cha.y)
  pos_cha.x = pos_cha.x / xiebian *speed 
  pos_cha.y = pos_cha.y / xiebian *speed
  //给小球赋值发射方向  向量
 selfNode.getComponent(RigidBody2D).linearVelocity=pos_cha;
}

/**
* 绘制 滚动列表 2
* @param contentNode 
* @param arr 
* @param prefab 
* @param componentName 
* @param transverseNum 
* @param transverseInterval 
* @param verticalInterval 
*/


export function drawScroll2(contentNode: cc.Node, arr: Array<any>, prefab: cc.Prefab, componentName: string, transverseNum: number = 1, transverseInterval: number = 0, verticalInterval: number = 0,DownYMun:number=-15, isOffEvent: boolean = true) {

  // console.log("componentName", componentName)
  let childs: Array<cc.Node> = contentNode.children;

  for (let k: number = 0; k < childs.length; k++) {

    childs[k].active = k < arr.length ? true : false;
    if (isOffEvent)
      childs[k].off(cc.Node.EventType.TOUCH_END);
  }

  if (!arr) {
    return;
  }
  for (let i: number = 0; i < arr.length; i++) {

    let pre: cc.Node = null;

    if (!childs[i]) {

      pre = cc.instantiate(prefab);

      pre.name = i + "";

      contentNode.addChild(pre);

      let posX = ((i % transverseNum) - transverseNum / 2) * (pre.width + transverseInterval) + (pre.width + transverseInterval) / 2;

      let posY = 0 - (pre.height / 2 + (pre.height + verticalInterval) * Math.floor(i / transverseNum));

      posY+=DownYMun;//微调，@杨上漂

      pre.setPosition(posX, posY);

      // setTimeout(() => {

      let preCont: any = pre.getComponent(componentName);

      preCont.drawUi(arr[i]);

      // }, 50 * i);

    } else {

      pre = childs[i];

      let preCont: any = pre.getComponent(componentName);

      preCont.drawUi(arr[i]);
    }


  }

  if (contentNode.children.length > 0) {

    contentNode.height = (contentNode.children[0].height + verticalInterval) * Math.ceil(arr.length / transverseNum) + 50;

    contentNode.width = (contentNode.children[0].width + transverseInterval) * transverseNum + 50;
  }

}

/**
* 绘制 滚动列表 2
* @param contentNode 
* @param arr 
* @param prefab 
* @param componentName 
* @param transverseNum 
* @param transverseInterval 
* @param verticalInterval 
*/
export function drawScroll(contentNode: cc.Node, arr: Array<any>, prefab: cc.Prefab, componentName: string, transverseNum: number = 1, transverseInterval: number = 0, verticalInterval: number = 0, isOffEvent: boolean = true) {

  // console.log("componentName", componentName)
  let childs: Array<cc.Node> = contentNode.children;

  for (let k: number = 0; k < childs.length; k++) {

    childs[k].active = k < arr.length ? true : false;
    if (isOffEvent)
      childs[k].off(cc.Node.EventType.TOUCH_END);
  }

  for (let i: number = 0; i < arr.length; i++) {

    let pre: cc.Node = null;

    if (!childs[i]) {

      pre = cc.instantiate(prefab);

      pre.name = i + "";

      contentNode.addChild(pre);

      // let posX = ((i % transverseNum) - transverseNum / 2) * (pre.width + transverseInterval) + (pre.width + transverseInterval) / 2;

      // let posY = 0 - (pre.height / 2 + (pre.height + verticalInterval) * Math.floor(i / transverseNum));

      // pre.setPosition(posX, posY);

      // setTimeout(() => {

      let preCont: any = pre.getComponent(componentName);

      console.debug(preCont+"component")
      preCont.drawUi(arr[i]);

      // }, 50 * i);

    } else {

      pre = childs[i];

      let preCont: any = pre.getComponent(componentName);

      preCont.drawUi(arr[i]);
    }


  }

}



/**
 * 倒计时 00:00:00
 * @param leftTime 时间
 * @returns 
 */
export function getTimehms(leftTime: number): string {

  if (leftTime <= 0) return "00:00:00";

  let str: string = "";

  let d = Math.floor(leftTime / 86400);

  let h = Math.floor(leftTime / 3600);

  if (d) {
    str = d + "天 ";

    h = Math.floor((leftTime % 86400) / 3600);
  }


  h < 10 ? (str += "0" + h) : (str += h);

  let m = h ? Math.floor(leftTime % 3600 / 60) : Math.floor(leftTime / 60);

  m < 10 ? (str += ":0" + m) : (str += ":" + m);

  let s = Math.floor(leftTime % 60);

  s < 10 ? (str += ":0" + s) : (str += ":" + s);

  return str;
}

export function limit(src: number, min: number, max: number) {
  return Math.min(max, Math.max(min, src));
}

export function removeButtonEvent(button: cc.Button, handler: string, target: cc.Node, component: string): void {
  for (let k = 0; k < button.clickEvents.length; ++k) {
    let evt: cc.Component.EventHandler = button.clickEvents[k];
    if (evt.target == target && evt.component == component && evt.handler == handler) {
      button.clickEvents.splice(k, 1);
      break;
    }
  }
}

export function addButtonEvent(button: cc.Button, handler: string, target: cc.Node, component: string, customData: string = null) {
  if (button != null) {
    var event = new cc.Component.EventHandler();
    event.target = target;
    event.component = component;
    event.handler = handler.toString();
    event.customEventData = customData;

    let hasEvent: boolean = false;
    for (let i_0 = 0; i_0 < button.clickEvents.length; i_0++) {
      if (compareEvents(button.clickEvents[i_0], event)) {
        hasEvent = true;
        break;
      }
    }

    if (!hasEvent)
      button.clickEvents.push(event);
  }
  else {
    //console.error("按钮缺失");
  }

  function compareEvents(event1: cc.Component.EventHandler, event2: cc.Component.EventHandler): boolean {
    if (event1.target != event2.target) {
      return false;
    }
    else if (event1.component != event2.component) {
      return false;
    }
    else if (event1.handler != event2.handler) {
      return false;
    }
    else if (event1.customEventData != event2.customEventData) {
      return false;
    }

    return true;
  }
}

export function seekNodeWithName2(name: string, root: cc.Node): cc.Node {

  let arr = name.split("/");

  let child: cc.Node = root;

  for (let i: number = 0; i < arr.length; i++) {
    // console.log(arr[i]);
    // console.log(child);
    child = child.getChildByName(arr[i]);
  }

  return child;
}

/**
 * 创建飞字
 * @param layer 
 * @param str 
 * @param $x 
 * @param $y 
 * @param $color 
 * @param size 
 */
export function createFlyTxt(
  layer: cc.Node,
  str: string,
  $x: number,
  $y: number,
  $color: string = "#ffffff",
  myNode: cc.Node = null,
) {

  if (!layer) return;

  let text = null;

  if (gameData.ins.poolObj['flyTxt'].size() > 0) {

    text = gameData.ins.poolObj['flyTxt'].get();
  } else {

    cc.resources.load(gameData.ins.preObj['flyTxt'], cc.Prefab, (err, res: any) => {

      gameData.ins.poolObj['flyTxt'].put(cc.instantiate(res));

      return;

    });
  }

  if (text) {

    let t: flyTxt = text.getComponent(flyTxt);

    if (t) {

      t.drawUi(str, $color);

    }

    text.active = true;

    text.opacity = 255;

    if (myNode && myNode.parent) {

      let worldPos = myNode.parent.convertToWorldSpaceAR(cc.v2($x, $y));

      let nodePos = layer.convertToNodeSpaceAR(worldPos);

      text.setPosition(nodePos.x, nodePos.y);

    } else {

      text.setPosition($x, $y);
    }

    layer.addChild(text);

    text.zIndex = 2;

    cc.tween(text)
      .to(0.3, { y: text.y + 30, opacity: 255 })
      .call(() => {
        cc.tween(text)
          .to(0.3, { opacity: 100 })
          .call(() => {
            t.recover();
          }, this).start();
      }, text)
      .start();

  }
}

/**
 * 计算暴击
 * @param baoji 
 * @param baoshang 
 * @param attack 
 */
export function computeBaoji(baoji: number, baoshang: number, attack: number): Array<any> {

  let tempAck: number = attack;

  let tempColor: string = "#FFFFFF";

  let wordStr: string = "";

  if (baoji && baoji > 0) {

    let baojiRandom: number = randomNum(0, 100);

    if (baojiRandom <= (baoji) * 100) {

      tempAck = Math.floor(attack * (baoshang + 1));

      tempColor = "#EA1212";

      wordStr = "暴击";
    }
  }
  return [Math.floor(tempAck), tempColor, wordStr];
}

/**
 * 是否起效
 */
export function compareAttr(num) {
  if (num && num > 0) {

    let numRandom: number = randomNum(0, 100);

    if (numRandom <= (num) * 100) {

      return true;
    }
  }
  return false;
}

/**
 * @description: 包含最大值和最小值
 * @param {number} min
 * @param {number} max
 * @return {*}
 */
export function randomNum(min: number, max: number) {

  let ret = Math.floor(Math.random() * (max - min + 1)) + min;

  return ret;
}


/**
 * 
 * @param key 
 */
export function getStartTime(key) {
  switch (key) {
    case 1:
      //今天开始时间
      return new Date(new Date().setHours(0, 0, 0));
    case 2:
      //本周开始时间
      return new Date(new Date().setHours(0, 0, 0) - (new Date().getDay() - 1) * 24 * 60 * 60 * 1000);
    case 3:
      //本月开始时间
      return new Date(new Date(new Date().getFullYear(), new Date().getMonth(), 1).setHours(0, 0, 0));
    case 4:
      //今年开始时间
      return new Date(new Date().getFullYear(), 0, 1);
  }
}
/**
* 
* @param key 
*/
export function getEndTime(key) {
  switch (key) {
    case 1:
      //今天结束时间
      return new Date().setHours(23, 59, 59, 999);
    case 2:
      //本周结束时间
      return new Date().setHours(0, 0, 0) + (7 - new Date().getDay()) * 24 * 60 * 60 * 1000;
    case 3:
      //本月结束时间
      return new Date(new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0).setHours(23, 59, 59, 59));
    case 4:
      //今年结束时间
      return new Date(new Date(new Date().getFullYear() + 1, 0, 0).setHours(23, 59, 59, 59));
  }
}

/**
 * 计算两点之间的直线距离
 * @param ownX 
 * @param ownY 
 * @param targetX 
 * @param targetY 
 */
export function getDistance(ownX: number, ownY: number, targetX: number, targetY: number) {

  return Math.sqrt(Math.pow((ownX - targetX), 2) + Math.pow((ownY - targetY), 2));
}


//单位换算
export function convertNumber(number) {
  if (number >= 1000000000) {
    return (number / 1000000000).toFixed(2) + "亿";
  } else if (number >= 10000) {
    return (number / 10000).toFixed(2) + "万";
  } else if (number >= 1000) {
    return (number / 1000).toFixed(2) + "千";
  } else {
    return number.toString();
  }
}

// // 示例用法
// 创建一个函数，接收一个数字作为参数。
// 判断数字的大小，根据不同的范围进行转换。
// 如果数字大于等于1亿（1,000,000,000），将数字除以1亿并保留两位小数，然后添加"亿"作为单位。
// 如果数字大于等于1万（10,000），将数字除以1万并保留两位小数，然后添加"万"作为单位。
// 如果数字大于等于1千（1,000），将数字除以1千并保留两位小数，然后添加"千"作为单位。
// 如果数字小于1千，直接返回原始数字。
// 返回转换后的字符串。
// console.log(convertNumber(123456789)); // 输出：1.23亿
// console.log(convertNumber(98765)); // 输出：9.88万
// console.log(convertNumber(5432)); // 输出：5.43千
// console.log(convertNumber(123)); // 输出：123


//两个数是否接近
export function isNearlyEqual(num1, num2, threshold=10) {
  // threshold = threshold || 0.000001; // 设定一个近似阈值，默认为1e-5
  return Math.abs(num1 - num2) < threshold;
}

//保留一位小数
export function keepOneDecimalFull(num: any) {
  let result = parseFloat(num);
  if (isNaN(result)) {
    return false;
  }

  // result = Math.round(num * 100) / 100;
  result = Math.floor(num * 10) / 10;
  let s_x = result.toString();
  let pos_decimal = s_x.indexOf(".");

  if (pos_decimal < 0) {
    pos_decimal = s_x.length;
    s_x += ".";
  }
  while (s_x.length <= pos_decimal + 1) {
    s_x += "0";
  }
  return s_x;
}

//保留n位小数并格式化输出（不足的部分补0）yangshangpiao
export function keepOneDecimalFullFomatFloat(value, n) {
  var f = Math.round(value * Math.pow(10, n)) / Math.pow(10, n);
  var s = f.toString();
  var rs = s.indexOf(".");
  if (rs < 0) {
    s += ".";
  }
  for (var i = s.length - s.indexOf("."); i <= n; i++) {
    s += "0";
  }
  return s;
};
// console.log(keepOneDecimalFullFomatFloat(1,2));    //1.00


//保留两位小数
export function keepOneDecimalFull2(num: any) {
  let result = parseFloat(num);
  if (isNaN(result)) {
    return false;
  }

  // result = Math.round(num * 100) / 100;
  result = Math.floor(num * 100) / 100;
  let s_x = result.toString();
  let pos_decimal = s_x.indexOf(".");

  if (pos_decimal < 0) {
    pos_decimal = s_x.length;
    s_x += ".";
  }
  while (s_x.length <= pos_decimal + 1) {
    s_x += "0";
  }
  return s_x;
}

  //格式化秒
  export function formatSeconds(value) {
    let secondTime = parseInt(value);// 秒
    let minuteTime = 0;// 分
    let hourTime = 0;// 小时
    let secondTimeForma: string;// 秒
    let minuteTimeForma: string;// 分
    let hourTimeForma: string// 小时
    if (secondTime > 60) {//如果秒数大于60，将秒数转换成整数
      //获取分钟，除以60取整数，得到整数分钟
      minuteTime = Math.trunc(secondTime / 60);
      //获取秒数，秒数取佘，得到整数秒数
      secondTime = secondTime % 60;
      //如果分钟大于60，将分钟转换成小时
      if (minuteTime > 60) {
        //获取小时，获取分钟除以60，得到整数小时
        hourTime = Math.trunc(minuteTime / 60);
        //获取小时后取佘的分，获取分钟除以60取佘的分
        minuteTime = minuteTime % 60;
      }
    }

    //格式化
    if (secondTime < 10) {
      secondTimeForma = "0" + secondTime;
    }
    else {
      secondTimeForma = secondTime.toString();
    }

    if (minuteTime < 10) {
      minuteTimeForma = "0" + minuteTime;
    }
    else {
      minuteTimeForma = minuteTime.toString();
    }

    if (hourTime < 10) {
      hourTimeForma = "0" + hourTime;
    }
    else {
      hourTimeForma = hourTime.toString();
    }

    return `${hourTimeForma}:${minuteTimeForma}:${secondTimeForma}`;
  }

  export function checkIsTody(time): boolean {
    var date = time;
    var dateNow = new Date();
    let bNewDay = false;

    if (date.getFullYear() == dateNow.getFullYear() &&
        date.getMonth() == dateNow.getMonth() &&
        date.getDate() == dateNow.getDate()
    ) {
        bNewDay = true;
    }
    return bNewDay;
}

  







